﻿//////////////////////////////////////////////////////////////////////////
//默认账号交易
//策略描述：
//默认账号进行交易，下单时不指定account

using GMSDK;
using System.Data;
using System;
using System.Linq;
using System.Collections.Generic;
using MathNet.Numerics.Financial;


namespace example_defaccount
{
    public class MyStrategy : Strategy
    {
        public MyStrategy(string token, string strategyId, StrategyMode mode) : base(token, strategyId, mode) { }

        string[] index = { "SHSE.000910", "SHSE.000909", "SHSE.000911", "SHSE.000912", "SHSE.000913", "SHSE.000914" };
        int date = 20;
        double ratio = 0.8;
        //重写OnInit事件，进行策略开发
        public override void OnInit()
        {
            System.Console.WriteLine("OnInit");
            // Subscribe("SHSE.600000,SZSE.000001", "1d");
            // 设置定时任务
            Schedule("1m", "09:40:00");
            return;
        }

        public override void OnSchedule(string dataRule, string timeRule)
        {
            base.OnSchedule(dataRule, timeRule);
            var today = Now().ToString("yyyy-MM-dd");
            var last_day = GMApi.GetPreviousTradingDate("SHSE", today).data.ToString("yyyy-MM-dd");
            List<float> return_index = new List<float>();
            // 获取并计算行业指数收益率
            foreach (var item in index)
            {
                var return_index_his = GMApi.HistoryBarsN(item, "1d", date, "", Adjust.ADJUST_PREV, "", true, "Last");
                var index_his = return_index_his.data.Select(p => p.close).ToList();
                return_index.Add(index_his.Last() / index_his.First() - 1);
            }

            // 获取指定数内收益率表现最好的行业
            var sector = index[return_index.IndexOf(return_index.Max())];
            Console.WriteLine($"最佳行业指数是: {sector}");
            // 获取最佳行业指数成份股
            var symboltable = GMApi.GetConstituents(sector, last_day).data;
            var symbollist = symboltable.AsEnumerable().Select(p => p.Field<string>("symbol").ToString()).ToList();
            var symbols = string.Join(",", symbollist);
            // 获取当天有交易的股票
            var not_suspended_info = GMApi.GetHistoryInstruments(symbols, today, today).data;
            var not_suspended_list = not_suspended_info.AsEnumerable()
                .Where(p => p.Field<Int32>("is_suspended") == 0)
                .Select(p => p.Field<string>("symbol").ToString()).ToList();
            var not_suspended_symbols = string.Join(",", not_suspended_list);
            // 获取最佳行业指数成份股的市值，从大到小排序并选取市值最大的5只股票
            var fin = GMApi.GetFundamentals("tq_sk_finindic", not_suspended_symbols, last_day,
                                last_day, "NEGOTIABLEMV", "", "-NEGOTIABLEMV", 5).data;
            var finindex = fin.AsEnumerable().Select(p => p.Field<string>("symbol")).ToList();
            //fin.index = fin['symbol']
            //// 计算权重
            var percent = 1.0 / finindex.Count * ratio;
            // 获取当前所有仓位
            var positions = GetPosition().data;//account().positions()

            // 如标的池有仓位,平不在标的池的仓位
            foreach (var position in positions)
            {
                var symbol = position.symbol;
                if (!finindex.Contains(symbol))
                {
                    OrderTargetPercent(symbol, 0, PositionSide.PositionSide_Long, OrderType.OrderType_Market);
                    Console.WriteLine($"市价单平不在标的池的, {symbol}");
                }

            }
            // 对标的池进行操作
            foreach (var item in finindex)
            {
                OrderTargetPercent(item, percent, PositionSide.PositionSide_Long, OrderType.OrderType_Market);
                Console.WriteLine($"{item} 以市价单调整至仓位 {percent}");
            }



        }

        //重写OnBar事件
        public override void OnBar(Bar bar)
        {
            //不指定account 使用默认账户下单
            OrderVolume(bar.symbol, 200, OrderSide.OrderSide_Buy, OrderType.OrderType_Market, PositionEffect.PositionEffect_Open, 0);
        }

        // 回测完成，收到绩效报告
        public override void OnBacktestFinished(Indicator indicator)
        {
            System.Console.WriteLine("OnIndicator：");
            System.Console.WriteLine("{0,-50}{1}", "账号ID：", indicator.accountId);
            System.Console.WriteLine("{0,-50}{1}", "累计收益率：", indicator.pnlRatio);
            System.Console.WriteLine("{0,-50}{1}", "年化收益率：", indicator.pnlRatioAnnual);
            System.Console.WriteLine("{0,-50}{1}", "夏普比率：", indicator.sharpRatio);
            System.Console.WriteLine("{0,-50}{1}", "最大回撤：", indicator.maxDrawdown);
            System.Console.WriteLine("{0,-50}{1}", "风险比率：", indicator.riskRatio);
            System.Console.WriteLine("{0,-50}{1}", "开仓次数：", indicator.openCount);
            System.Console.WriteLine("{0,-50}{1}", "平仓次数：", indicator.closeCount);
            System.Console.WriteLine("{0,-50}{1}", "盈利次数：", indicator.winCount);
            System.Console.WriteLine("{0,-50}{1}", "亏损次数：", indicator.loseCount);
            System.Console.WriteLine("{0,-50}{1}", "胜率：", indicator.winRatio);
            System.Console.WriteLine("{0,-50}{1}", "指标创建时间：", indicator.createdAt);
            System.Console.WriteLine("{0,-50}{1}", "指标变更时间：", indicator.updatedAt);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyStrategy s = new MyStrategy("ba65244a12228fe5c10cf8603723ee0533476270", "cf0a06ba-6e78-11eb-be17-5e7c0c44a9d3", StrategyMode.MODE_BACKTEST);
            s.SetBacktestConfig("2020-07-01 17:20:00",
                "2020-10-01 17:30:00",
                10000,  // 回测初始资金, 默认1000000
                1, // 回测成交比例, 默认1.0, 即下单100%成交
                0.0001, // 回测佣金比例, 默认0
                0.0001, // 回测滑点比例, 默认0
                Adjust.ADJUST_PREV);    // 复权方式，参见 enum Adjust
            s.Run();
            System.Console.WriteLine("回测完成！");
            System.Console.Read();
        }
    }
}